**&--------------------------「程序说明-START」------------------------*
*
**& ReportName:     ZTABIMP
*
**& Packet:         ZDEV
*
**& Author:         ZYH
*
**& CreatedDate:   19.05.2022 09:04:52
*
**& Intention :    通用自定义表维护程序
*
**& Version :      1.0.0.0
**&--------------------------「程序说明-END」--------------------------*
REPORT  ZTABIMP .

***********************************************************************
**----------------------------T Y P E S------------------------------**
***********************************************************************
TYPE-POOLS:ICON.

***********************************************************************
**---------------------------T A B L E S-----------------------------**
***********************************************************************
TABLES: SSCRFIELDS.

***********************************************************************
**------------------------V A R I A B L E S--------------------------**
***********************************************************************
FIELD-SYMBOLS:<DYN_TABLE> TYPE STANDARD TABLE,                  "数据表"
              <DYN_WA>    TYPE ANY,                             "数据工作区"
              <DYN_FIELD> TYPE DATA.                            "数据字段"

DATA:DYN_WA               TYPE REF TO DATA,                     "结构数据对象"
     DYN_TABLE            TYPE REF TO DATA.                     "表数据对象"

DATA:GT_FIELDCAT          TYPE LVC_T_FCAT,                      "字段目录
     GS_LAYOUT            TYPE LVC_S_LAYO,                      "布局
     GS_SETTING           TYPE LVC_S_GLAY.                      "设置

DATA:OK_CODE              TYPE SY-UCOMM,                        "功能码
     SAVE_OK              TYPE SY-UCOMM.

DATA:GR_CONTAINER         TYPE REF TO CL_GUI_CUSTOM_CONTAINER,  "容器"
     GR_TABLE             TYPE REF TO CL_GUI_ALV_GRID.          "容器实例"

DATA GT_TABLE             TYPE TABLE OF DNTAB.                  "字段结构表
DATA GS_TABLE             TYPE DNTAB.                           "字段工作区"

DATA:GS_EDIT_CELL         TYPE LVC_S_STYL,                      "字段编辑工作区"
     GT_EDIT_CELL         TYPE LVC_T_STYL.                      "字段编辑结构表"

DATA:GT_FIELDS_TAB        TYPE STANDARD TABLE OF RSDSFIELDS,    "动态筛选条件结果集"
     GT_WHERE_CLAUSES     TYPE RSDS_TWHERE.                     "动态选择屏幕条件值"

DATA:GV_SQL_WHERE         TYPE STRING.                          "动态SQL"
*----------------------------------------------------------------------*
*       CLASS LCL_EVENT_RECEIVER DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS LCL_EVENT_RECEIVER DEFINITION.                  "定义类
  PUBLIC SECTION.
    METHODS:
*     工具栏
      HANDLE_TOOLBAR               FOR EVENT TOOLBAR               OF CL_GUI_ALV_GRID
        IMPORTING E_OBJECT E_INTERACTIVE,

*     用户响应事件
      HANDLE_USER_COMMAND          FOR EVENT USER_COMMAND          OF CL_GUI_ALV_GRID
        IMPORTING E_UCOMM,

*     双击事件
      HANDLE_DOUBLE_CLICK          FOR EVENT DOUBLE_CLICK          OF CL_GUI_ALV_GRID
        IMPORTING E_ROW E_COLUMN,

*     热点事件
      HANDLE_HOTSPOT_CLICK         FOR EVENT HOTSPOT_CLICK         OF CL_GUI_ALV_GRID
        IMPORTING E_ROW_ID E_COLUMN_ID,

*     ALV数据修改事件
      HANDLE_DATA_CHANGED          FOR EVENT DATA_CHANGED          OF CL_GUI_ALV_GRID
        IMPORTING ER_DATA_CHANGED E_ONF4 E_ONF4_BEFORE E_ONF4_AFTER E_UCOMM,

*     ALV数据修改完成事件
      HANDLE_DATA_CHANGED_FINISHED FOR EVENT DATA_CHANGED_FINISHED OF CL_GUI_ALV_GRID
        IMPORTING E_MODIFIED ET_GOOD_CELLS.

ENDCLASS.                    "LCL_EVENT_RECEIVER DEFINITION


DATA GR_EVENT_RECEIVER TYPE REF TO LCL_EVENT_RECEIVER.   "声明一个类变量，用来装载类实例

***********************************************************************
**-----------------S E L E C T I O N---S C R E E N-------------------**
***********************************************************************
SELECTION-SCREEN BEGIN OF BLOCK BLK1 WITH FRAME TITLE TEXT-T01.
* 表名称
  PARAMETERS:P_TABLE TYPE TABNAME DEFAULT 'Z'.
  SELECTION-SCREEN BEGIN OF BLOCK BLK3 WITH FRAME TITLE TEXT-T03.
* 单个维护
    PARAMETERS:R_ADD_S RADIOBUTTON GROUP G2 MODIF ID RAD DEFAULT 'X' USER-COMMAND SMD.
    SELECTION-SCREEN BEGIN OF BLOCK BLK5 WITH FRAME TITLE TEXT-T05.
* 单个基础维护
      PARAMETERS:R_LOW  RADIOBUTTON GROUP G3 MODIF ID CHK DEFAULT 'X',
* 单个高级维护
                 R_HIGH RADIOBUTTON GROUP G3 MODIF ID CHK.
    SELECTION-SCREEN END OF BLOCK BLK5.
* 批量维护
    PARAMETERS:R_ADD_M RADIOBUTTON GROUP G2 MODIF ID RAD.
* 是否显示数据条目
    PARAMETERS:CHK_SHOW AS CHECKBOX MODIF ID CHK DEFAULT 'X' USER-COMMAND CMD.
* 显示条目数
    PARAMETERS:P_LINES TYPE INT1 DEFAULT '50' MODIF ID LIN.
    SELECTION-SCREEN BEGIN OF BLOCK BLK4 WITH FRAME TITLE TEXT-T04.
* EXCEL文件路径
      PARAMETERS:P_FILE  TYPE RLGRAP-FILENAME LOWER CASE MODIF ID MFN.
* 起始行
      PARAMETERS P_ROW   TYPE N LENGTH 2 DEFAULT '2' OBLIGATORY MODIF ID MFN.
* 起始列
      PARAMETERS P_COL   TYPE N LENGTH 2 DEFAULT '1' OBLIGATORY MODIF ID MFN.
    SELECTION-SCREEN END OF BLOCK BLK4.
  SELECTION-SCREEN END OF BLOCK BLK3.
* 增强模式:勾选此选项可忽略自定义表的检查
  PARAMETERS:CHK_BUG AS CHECKBOX DEFAULT ''.
SELECTION-SCREEN END OF BLOCK BLK1.

* 备注:
SELECTION-SCREEN COMMENT 5(75) TEXT-006.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT 5(75) TEXT-007.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT 5(75) TEXT-008.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT 5(75) TEXT-009.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT 5(75) TEXT-010.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT 5(75) TEXT-011.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT 5(75) TEXT-012.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT 5(75) TEXT-005.
SELECTION-SCREEN FUNCTION KEY 1.



* 选择块描述:直接复制到文本元素即可
*005  备注:1.没有颜色的列为主键列,不能更改! 2.批量维护时请下载模板! 35  70
*006  使用说明: 5 15
*007  -----单个维护:  10  14
*008                 新增:点击新增按钮，输入记录，点击工具栏的保存按钮即可； 43  70
*009                 修改:勾选需要修改的记录，更改有颜色的列，点击工具栏的保存按钮即可； 49  82
*010                 删除:勾选需要删除的记录，点击工具栏的删除按钮即可； 41  66
*011  -----批量维护:  10  14
*012                新增:输入表名，下载模板，填充数据，加载模板，点击工具栏的全选按钮，再点击保存按钮即可；  58  116

* 选择文本描述:直接复制到文本元素即可
*CHK_BUG  增强模式(不要轻易使用)
*CHK_SHOW	是否显示数据
*P_COL  开始列
*P_FILE	文件路径
*P_LINES  数据条目:
*P_ROW  开始行
*P_TABLE  表名
*R_ADD_M  批量维护
*R_ADD_S  单个维护
*R_HIGH	高级维护
*R_LOW  基础维护

***********************************************************************
**-------------------I N I T I A L I Z A T I O N---------------------**
***********************************************************************
INITIALIZATION.
* 模板下载
  SSCRFIELDS-FUNCTXT_01 = '@49@下载模板'.


* 批量维护模板下载
AT SELECTION-SCREEN.
  CASE SSCRFIELDS-UCOMM.
    WHEN 'FC01'.
      PERFORM DOWNLOAD_TEMPLATE USING P_TABLE .
  ENDCASE.

* 屏幕演变
AT SELECTION-SCREEN OUTPUT.
  LOOP AT SCREEN .
    CASE SCREEN-GROUP1.
      WHEN 'MFN'.
        IF R_ADD_M = 'X' .
          SCREEN-ACTIVE = 1.
        ELSE.
          SCREEN-ACTIVE = 0.
        ENDIF.
      WHEN 'CHK'.
        IF R_ADD_S = 'X'.
          SCREEN-ACTIVE = 1.
        ELSE.
          SCREEN-ACTIVE = 0.
        ENDIF.
      WHEN 'LIN'.
        IF CHK_SHOW = 'X'.
          SCREEN-ACTIVE = 1.
        ELSE.
          SCREEN-ACTIVE = 0.
        ENDIF.
      WHEN OTHERS.
    ENDCASE.
    MODIFY SCREEN.
  ENDLOOP.

* 表输入自定义搜索帮助
AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_TABLE.
  PERFORM FRM_HELP_F4_TABLE USING P_TABLE.

* 文件输入搜索帮助
AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_FILE.
  PERFORM SELECT_EXCEL_FILE CHANGING P_FILE.  "选择EXCEL文件"
  PERFORM FRM_CHECK_FILE_EXIST USING P_FILE.  "检查文件是否存在"


***********************************************************************
**-----------------S T A R T-O F-S E L E C T I O N-------------------**
***********************************************************************
START-OF-SELECTION.
  IF CHK_BUG = ''.                                "一般模式"
    IF P_TABLE IS INITIAL.
      MESSAGE '请输入表名' TYPE 'S' DISPLAY LIKE 'E'.
      LEAVE LIST-PROCESSING.
    ELSE.
      PERFORM FRM_TABLE_CHECK USING P_TABLE.      "表检查"
    ENDIF.
  ENDIF.
  PERFORM FRM_CREATE_TABLE.                       "创建表结构"
  IF R_ADD_M = 'X'.
    IF P_FILE IS INITIAL .
      MESSAGE '请输入EXCEL文件路径!' TYPE 'S' DISPLAY LIKE 'E' .
      LEAVE LIST-PROCESSING.
    ELSE.
      PERFORM FRM_LOAD_EXCEL USING P_ROW P_COL.   "加载EXCEL数据"
    ENDIF.
  ELSE.
    IF R_HIGH = 'X'.                              "单个高级维护"
      PERFORM FRM_CALL_SE16N.
      LEAVE LIST-PROCESSING.
    ELSE.
      PERFORM FRM_SELECTION_INI.                  "初始化选择屏幕"
      PERFORM FRM_FILTER_DATA.                    "过滤数据"
      PERFORM FRM_GET_DATA.                       "获取数据"
    ENDIF.
  ENDIF.
  PERFORM FRM_SET_EDIT.                           "设置编辑状态"
  CALL SCREEN 9001.




*&---------------------------------------------------------------------*
*& Form frm_selection_ini
*&---------------------------------------------------------------------*
*& 选择屏幕条件初始化
*&---------------------------------------------------------------------*
FORM FRM_SELECTION_INI .
  DATA: LV_SELECTION_ID TYPE RSDYNSEL-SELID,
        LT_TABLES_TAB   TYPE STANDARD TABLE OF RSDSTABS,
        LS_TABLES_TAB   TYPE RSDSTABS.

  LS_TABLES_TAB-PRIM_TAB = P_TABLE.  "数据库表名
  APPEND LS_TABLES_TAB TO LT_TABLES_TAB.
  CALL FUNCTION 'FREE_SELECTIONS_INIT'
    EXPORTING
      KIND                     = 'T'
    IMPORTING
      SELECTION_ID             = LV_SELECTION_ID
    TABLES
      TABLES_TAB               = LT_TABLES_TAB
    EXCEPTIONS
      FIELDS_INCOMPLETE        = 1
      FIELDS_NO_JOIN           = 2
      FIELD_NOT_FOUND          = 3
      NO_TABLES                = 4
      TABLE_NOT_FOUND          = 5
      EXPRESSION_NOT_SUPPORTED = 6
      INCORRECT_EXPRESSION     = 7
      ILLEGAL_KIND             = 8
      AREA_NOT_FOUND           = 9
      INCONSISTENT_AREA        = 10
      KIND_F_NO_FIELDS_LEFT    = 11
      KIND_F_NO_FIELDS         = 12
      TOO_MANY_FIELDS          = 13
      DUP_FIELD                = 14
      FIELD_NO_TYPE            = 15
      FIELD_ILL_TYPE           = 16
      DUP_EVENT_FIELD          = 17
      NODE_NOT_IN_LDB          = 18
      AREA_NO_FIELD            = 19
      OTHERS                   = 20.
  IF SY-SUBRC EQ 0.
    CALL FUNCTION 'FREE_SELECTIONS_DIALOG'
      EXPORTING
        SELECTION_ID    = LV_SELECTION_ID
        TITLE           = '选择'
        FRAME_TEXT      = '查询条件'
        AS_WINDOW       = ''                "不显示成窗口
      IMPORTING
        WHERE_CLAUSES   = GT_WHERE_CLAUSES  "返回选择条件
      TABLES
        FIELDS_TAB      = GT_FIELDS_TAB     "选择画面中选中字段
      EXCEPTIONS
        INTERNAL_ERROR  = 1
        NO_ACTION       = 2
        SELID_NOT_FOUND = 3
        ILLEGAL_STATUS  = 4
        OTHERS          = 5.
  ENDIF.


ENDFORM.                    "FRM_SELECTION_INI
*----------------------------------------------------------------------*
*       CLASS LCL_EVENT_RECEIVER IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS LCL_EVENT_RECEIVER IMPLEMENTATION.
*  工具栏的实现
  METHOD HANDLE_TOOLBAR.
    DATA:LS_TB_BUTTON TYPE STB_BUTTON,
         LT_TB_BUTTON TYPE TTB_BUTTON.

    CLEAR:LT_TB_BUTTON.
    LS_TB_BUTTON-FUNCTION = 'ADD'.
    LS_TB_BUTTON-ICON = ICON_INSERT_ROW.
    LS_TB_BUTTON-TEXT = '新增'.
    LS_TB_BUTTON-QUICKINFO = '新增'.
    APPEND LS_TB_BUTTON TO LT_TB_BUTTON.
    LS_TB_BUTTON-FUNCTION = 'MOD'.
    LS_TB_BUTTON-ICON = ICON_CHANGE.
    LS_TB_BUTTON-TEXT = '修改'.
    LS_TB_BUTTON-QUICKINFO = '修改'.
    APPEND LS_TB_BUTTON TO LT_TB_BUTTON.
    LS_TB_BUTTON-FUNCTION = 'DEL'.
    LS_TB_BUTTON-ICON = ICON_DELETE_ROW.
    LS_TB_BUTTON-TEXT = '删除'.
    LS_TB_BUTTON-QUICKINFO = '删除'.
    APPEND LS_TB_BUTTON TO LT_TB_BUTTON.
    LS_TB_BUTTON-FUNCTION = 'SAVE'.
    LS_TB_BUTTON-ICON = ICON_SYSTEM_SAVE.
    LS_TB_BUTTON-TEXT = '保存'.
    LS_TB_BUTTON-QUICKINFO = '保存'.
    APPEND LS_TB_BUTTON TO LT_TB_BUTTON.
    LS_TB_BUTTON-FUNCTION = 'REFRESH'.
    LS_TB_BUTTON-ICON = ICON_REFRESH.
    LS_TB_BUTTON-TEXT = '刷新'.
    LS_TB_BUTTON-QUICKINFO = '刷新'.
    APPEND LS_TB_BUTTON TO LT_TB_BUTTON.
    LS_TB_BUTTON-FUNCTION = 'SALL'.
    LS_TB_BUTTON-ICON = ICON_SELECT_ALL.
    LS_TB_BUTTON-TEXT = '全选'.
    LS_TB_BUTTON-QUICKINFO = '全选'.
    APPEND LS_TB_BUTTON TO LT_TB_BUTTON.
    LS_TB_BUTTON-FUNCTION = 'DSALL'.
    LS_TB_BUTTON-ICON = ICON_DESELECT_ALL.
    LS_TB_BUTTON-TEXT = '取消全选'.
    LS_TB_BUTTON-QUICKINFO = '取消全选'.
    APPEND LS_TB_BUTTON TO LT_TB_BUTTON.

    E_OBJECT->MT_TOOLBAR = LT_TB_BUTTON.
  ENDMETHOD.                    "HANDLE_TOOLBAR
* z自定义事件
  METHOD  HANDLE_USER_COMMAND.

    CASE E_UCOMM.
      WHEN 'SALL'.
        PERFORM FRM_SALL_DATA.
      WHEN 'DSALL'.
        PERFORM FRM_DSALL_DATA.
      WHEN 'REFRESH'.

        CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
          EXPORTING
            PERCENTAGE = 50
            TEXT       = '正在刷新，请稍等'.
        PERFORM FRM_REFRESH_DATA.
      WHEN 'ADD'.
        PERFORM FRM_ADD_ITEM.
      WHEN 'MOD'.
        PERFORM FRM_MOD_ITEM.
      WHEN 'SAVE'.
        PERFORM FRM_SAVE_DB.
      WHEN 'DEL'.
        PERFORM FRM_DEL_ITEM.
      WHEN OTHERS.
    ENDCASE.
    CALL METHOD GR_TABLE->REFRESH_TABLE_DISPLAY.
  ENDMETHOD.                    "handle_toolbar
* 双击事件
  METHOD HANDLE_DOUBLE_CLICK.
  ENDMETHOD.                    "HANDLE_DOUBLE_CLICK
*  热点事件
  METHOD HANDLE_HOTSPOT_CLICK.
  ENDMETHOD.                    "HANDLE_HOTSPOT_CLICK
*
  METHOD HANDLE_DATA_CHANGED.
  ENDMETHOD.                    "HANDLE_DATA_CHANGED
  METHOD HANDLE_DATA_CHANGED_FINISHED.
  ENDMETHOD.                    "HANDLE_DATA_CHANGED_FINISHED
ENDCLASS.                    "lcl_event_receiver IMPLEMENTATION
*&---------------------------------------------------------------------*
*& Form FRM_CREATE_TABLE
*&---------------------------------------------------------------------*
*& 获取表结构
*&---------------------------------------------------------------------*
FORM FRM_CREATE_TABLE .
  DATA LS_STRUCT TYPE REF TO CL_ABAP_STRUCTDESCR.
  DATA LR_TABLE TYPE REF TO CL_ABAP_TABLEDESCR.
  DATA LR_TYPE TYPE REF TO CL_ABAP_TYPEDESCR.
  DATA LR_DATA TYPE REF TO CL_ABAP_DATADESCR.
  DATA LT_COMP TYPE ABAP_COMPONENT_TAB.
  DATA LS_COMP LIKE LINE OF LT_COMP.
  DATA L_STRING TYPE STRING.

  CALL FUNCTION 'NAMETAB_GET'                 "获取表结构字段"
    EXPORTING
      LANGU               = SY-LANGU
      ONLY                = 'X'
      TABNAME             = P_TABLE
    TABLES
      NAMETAB             = GT_TABLE
    EXCEPTIONS
      INTERNAL_ERROR      = 1
      TABLE_HAS_NO_FIELDS = 2
      TABLE_NOT_ACTIV     = 3
      NO_TEXTS_FOUND      = 4
      OTHERS              = 5.


  SORT GT_TABLE BY POSITION.                 "解析表结构"
  LOOP AT GT_TABLE INTO GS_TABLE.
    CONCATENATE GS_TABLE-TABNAME '-' GS_TABLE-FIELDNAME INTO L_STRING.
    LS_COMP-NAME = GS_TABLE-FIELDNAME.
*读取字段类型
    CALL METHOD CL_ABAP_DATADESCR=>DESCRIBE_BY_NAME
      EXPORTING
        P_NAME         = L_STRING
      RECEIVING
        P_DESCR_REF    = LR_TYPE
      EXCEPTIONS
        TYPE_NOT_FOUND = 1
        OTHERS         = 2.
    IF SY-SUBRC <> 0.
      MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
      WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    ENDIF.
    LS_COMP-TYPE ?= LR_TYPE.
    APPEND LS_COMP TO LT_COMP.
    CLEAR LS_COMP.
*   添加编辑样式
    GS_EDIT_CELL-FIELDNAME = GS_TABLE-FIELDNAME.
    GS_EDIT_CELL-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
    INSERT GS_EDIT_CELL INTO TABLE GT_EDIT_CELL.
  ENDLOOP.


*   添加编辑字段
  CLEAR:L_STRING.
  L_STRING = 'LVC_T_STYL'.
  CALL METHOD CL_ABAP_DATADESCR=>DESCRIBE_BY_NAME
    EXPORTING
      P_NAME         = L_STRING
    RECEIVING
      P_DESCR_REF    = LR_TYPE
    EXCEPTIONS
      TYPE_NOT_FOUND = 1
      OTHERS         = 2.

  LS_COMP-NAME = 'EDITCELL'.
  LS_COMP-TYPE ?= LR_TYPE.
  APPEND LS_COMP TO LT_COMP.

*   添加选择框字段
  CLEAR:L_STRING.
  L_STRING = 'CHAR01'.
  CALL METHOD CL_ABAP_DATADESCR=>DESCRIBE_BY_NAME
    EXPORTING
      P_NAME         = L_STRING
    RECEIVING
      P_DESCR_REF    = LR_TYPE
    EXCEPTIONS
      TYPE_NOT_FOUND = 1
      OTHERS         = 2.

  LS_COMP-NAME = 'SEL'.
  LS_COMP-TYPE ?= LR_TYPE.
  APPEND LS_COMP TO LT_COMP.


*根据动态字段结构创建结构
  CALL METHOD CL_ABAP_STRUCTDESCR=>CREATE
    EXPORTING
      P_COMPONENTS = LT_COMP
    RECEIVING
      P_RESULT     = LS_STRUCT.
*根据动态结构类型创建动态内表
  CALL METHOD CL_ABAP_TABLEDESCR=>CREATE
    EXPORTING
      P_LINE_TYPE = LS_STRUCT
    RECEIVING
      P_RESULT    = LR_TABLE.
*参照动态结构类型和动态内表类型创建内表与工作区
  CREATE DATA DYN_WA TYPE HANDLE LS_STRUCT.
  CREATE DATA DYN_TABLE TYPE HANDLE LR_TABLE.
*引用内表和工作区
  ASSIGN DYN_WA->* TO <DYN_WA>.
  ASSIGN DYN_TABLE->* TO <DYN_TABLE>.

ENDFORM.                    "FRM_CREATE_TABLE
*&---------------------------------------------------------------------*
*& Form FRM_TABLE_CHECK
*&---------------------------------------------------------------------*
*&  表检查
*&---------------------------------------------------------------------*
FORM FRM_TABLE_CHECK USING UV_TABLE.
  DATA:LV_MESSAGE TYPE C LENGTH 200.
  "只允许修改Z\Y开头的自定义表"
  IF UV_TABLE+0(1) <> 'Z' AND UV_TABLE+0(1) <> 'Y'.
    CONCATENATE '请输入Z或者Y开头的表名称!' LV_MESSAGE INTO LV_MESSAGE.
  ELSE.
    SELECT COUNT(*)  FROM DD02L WHERE TABNAME =  UV_TABLE.
    IF SY-SUBRC <> 0.
      CONCATENATE '输入的表名称在数据库中不存在!' LV_MESSAGE INTO LV_MESSAGE.
    ENDIF.
  ENDIF.
  IF LV_MESSAGE IS NOT INITIAL.
    MESSAGE LV_MESSAGE TYPE 'S' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.
ENDFORM.                    "FRM_TABLE_CHECK
*&---------------------------------------------------------------------*
*& Form FRM_HELP_F4_TABLE
*&---------------------------------------------------------------------*
*& 表搜索帮助
*&---------------------------------------------------------------------*
FORM FRM_HELP_F4_TABLE USING UV_TABLE.
  DATA:BEGIN OF TY_TABLE,
         TABNAME TYPE DD02L-TABNAME,
         DDTEXT  TYPE DD02T-DDTEXT,
       END OF TY_TABLE.
  DATA:LT_DD02L  LIKE TABLE OF TY_TABLE .
  DATA:LV_TABLE  TYPE C LENGTH 2 VALUE 'Z%'.
  "获取表数据"
  SELECT A~TABNAME T~DDTEXT
  INTO CORRESPONDING FIELDS OF TABLE LT_DD02L
  FROM DD02L AS A
  LEFT OUTER JOIN DD02T AS T ON T~TABNAME = A~TABNAME
  WHERE A~TABNAME LIKE LV_TABLE
  AND  A~TABCLASS = 'TRANSP'.

  "过滤重复数据"
  SORT LT_DD02L BY TABNAME .
  DELETE ADJACENT DUPLICATES FROM LT_DD02L COMPARING TABNAME.

  CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
    EXPORTING
      RETFIELD        = 'TABNAME'
      DYNPPROG        = SY-REPID
      DYNPNR          = SY-DYNNR
      DYNPROFIELD     = 'P_TABLE'
      VALUE_ORG       = 'S'
    TABLES
      VALUE_TAB       = LT_DD02L
    EXCEPTIONS
      PARAMETER_ERROR = 1
      NO_VALUES_FOUND = 2
      OTHERS          = 3.
ENDFORM.                    "FRM_HELP_F4_TABLE
*&---------------------------------------------------------------------*
*&      FORM  SELECT_EXCEL_FILE
*&---------------------------------------------------------------------*
*       TEXT
*----------------------------------------------------------------------*
FORM SELECT_EXCEL_FILE CHANGING P_FILE.
  DATA: LT_FILETABLE TYPE FILETABLE WITH HEADER LINE,
        L_RC         TYPE I,
        L_ACTION     TYPE I.

  CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_OPEN_DIALOG
    EXPORTING
      DEFAULT_EXTENSION = 'XLS'
      DEFAULT_FILENAME  = '*.XLS;*.XLSX'
      FILE_FILTER       = CL_GUI_FRONTEND_SERVICES=>FILETYPE_EXCEL
      MULTISELECTION    = ''
    CHANGING
      FILE_TABLE        = LT_FILETABLE[]
      RC                = L_RC
      USER_ACTION       = L_ACTION
    EXCEPTIONS
      OTHERS            = 1.
  IF L_ACTION NE 0.
    EXIT.
  ENDIF.

  READ TABLE LT_FILETABLE INDEX 1.
  P_FILE = LT_FILETABLE-FILENAME.

ENDFORM.                    "SELECT_EXCEL_FILE

*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DATA
*&---------------------------------------------------------------------*
*      获取数据
*----------------------------------------------------------------------*
FORM FRM_GET_DATA .
  FREE:<DYN_TABLE>.
*从动态表中取数到动态内表中
  IF CHK_SHOW = 'X'.
    IF GV_SQL_WHERE = ''.
      SELECT * INTO CORRESPONDING FIELDS OF TABLE <DYN_TABLE>  FROM (P_TABLE) UP TO P_LINES ROWS .
    ELSE.
      SELECT * INTO CORRESPONDING FIELDS OF TABLE <DYN_TABLE>  FROM (P_TABLE) UP TO P_LINES ROWS WHERE (GV_SQL_WHERE).
    ENDIF.
  ENDIF.
ENDFORM.                    " FRM_GET_DATA
*&---------------------------------------------------------------------*
*&      Form  FRM_SET_EDIT
*&---------------------------------------------------------------------*
*       设置可编辑字段
*----------------------------------------------------------------------*
FORM FRM_SET_EDIT .
  LOOP AT <DYN_TABLE> ASSIGNING <DYN_WA>.
    ASSIGN COMPONENT 'MANDT' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
    IF <DYN_FIELD> IS ASSIGNED.
      <DYN_FIELD> = SY-MANDT.
    ENDIF.
    ASSIGN COMPONENT 'EDITCELL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
    IF <DYN_FIELD> IS ASSIGNED.
      <DYN_FIELD> = GT_EDIT_CELL.    "初始化不可编辑"
    ENDIF.
  ENDLOOP.
ENDFORM.                    " FRM_SET_EDIT
*&---------------------------------------------------------------------*
*&      Form  FRM_DISPLAY_DATA
*&---------------------------------------------------------------------*
*       展示数据
*----------------------------------------------------------------------*
FORM FRM_DISPLAY_DATA .
  PERFORM FRM_SET_LAYOUT.            "设置布局"
  PERFORM FRM_SET_FIELDCAT.          "设置字段目录"
  PERFORM FRM_ALV_DISPLAY.           "ALV展示
ENDFORM.                    " FRM_DISPLAY_DATA
*&---------------------------------------------------------------------*
*&      Form  FRM_SET_LAYOUT
*&---------------------------------------------------------------------*
*       设置布局
*----------------------------------------------------------------------*
FORM FRM_SET_LAYOUT .
  CLEAR GS_LAYOUT.
  GS_LAYOUT-ZEBRA = 'X'.             "斑马线
  GS_LAYOUT-CWIDTH_OPT = 'X'.        "自动调整列宽
*  GS_LAYOUT-BOX_FNAME = 'SEL'.      "选择列
*  gs_layout-sel_mode = 'D'.          "OOALV中，设置左边选择列
  GS_LAYOUT-STYLEFNAME = 'EDITCELL'. "OOALV中，设置单元格编辑样式
ENDFORM.                    " FRM_SET_LAYOUT
*&---------------------------------------------------------------------*
*&      Form  FRM_SET_FIELDCAT
*&---------------------------------------------------------------------*
*       设置字段目录
*----------------------------------------------------------------------*
FORM FRM_SET_FIELDCAT .
  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
*     I_BUFFER_ACTIVE        =
      I_STRUCTURE_NAME       = P_TABLE "结构名称"
      I_CLIENT_NEVER_DISPLAY = 'X'
*     I_BYPASSING_BUFFER     =
*     I_INTERNAL_TABNAME     =
    CHANGING
      CT_FIELDCAT            = GT_FIELDCAT. "ALV字段目录内表"

  DATA:LS_FIELDCAT TYPE LVC_S_FCAT.
  LS_FIELDCAT-EDIT = 'X'.
  MODIFY GT_FIELDCAT FROM LS_FIELDCAT TRANSPORTING EDIT WHERE FIELDNAME <> 'MANDT'.
  CLEAR:LS_FIELDCAT.
  LS_FIELDCAT-EMPHASIZE = 'C410'.
  MODIFY GT_FIELDCAT FROM LS_FIELDCAT TRANSPORTING EMPHASIZE WHERE KEY = '' AND FIELDNAME <> 'MANDT'.
  CLEAR:LS_FIELDCAT.
  LS_FIELDCAT-EDIT = 'X'.
  LS_FIELDCAT-CHECKBOX = 'X'.
  LS_FIELDCAT-REPTEXT = '请选择'.
  LS_FIELDCAT-FIELDNAME = 'SEL'.
  APPEND LS_FIELDCAT TO GT_FIELDCAT.

ENDFORM.                    " FRM_SET_FIELDCAT
*&---------------------------------------------------------------------*
*&      Form  FRM_ALV_DISPLAY
*&---------------------------------------------------------------------*
*       ALV展示
*----------------------------------------------------------------------*
FORM FRM_ALV_DISPLAY .
  IF <DYN_TABLE> IS NOT ASSIGNED .
    EXIT.
  ENDIF.
  DATA : LT_EXCL_FUNC TYPE UI_FUNCTIONS.
  "设置不展示的按钮
  APPEND CL_GUI_ALV_GRID=>MC_FC_LOC_COPY       TO LT_EXCL_FUNC.
  APPEND CL_GUI_ALV_GRID=>MC_FC_LOC_COPY_ROW   TO LT_EXCL_FUNC.
  APPEND CL_GUI_ALV_GRID=>MC_FC_LOC_CUT        TO LT_EXCL_FUNC.
  APPEND CL_GUI_ALV_GRID=>MC_FC_DATA_SAVE      TO LT_EXCL_FUNC.
  APPEND CL_GUI_ALV_GRID=>MC_FC_INFO           TO LT_EXCL_FUNC.
  APPEND CL_GUI_ALV_GRID=>MC_FC_LOC_DELETE_ROW TO LT_EXCL_FUNC.
  APPEND CL_GUI_ALV_GRID=>MC_FC_LOC_INSERT_ROW TO LT_EXCL_FUNC.
  APPEND CL_GUI_ALV_GRID=>MC_FC_LOC_APPEND_ROW TO LT_EXCL_FUNC.
  APPEND CL_GUI_ALV_GRID=>MC_FC_DELETE_FILTER  TO LT_EXCL_FUNC.

  IF GR_CONTAINER IS NOT BOUND.
    IF CL_SALV_TABLE=>IS_OFFLINE( ) EQ IF_SALV_C_BOOL_SAP=>FALSE.
      CREATE OBJECT GR_CONTAINER
        EXPORTING
          CONTAINER_NAME = 'CONTAIN'.
*          side      = cl_gui_docking_container=>dock_at_bottom
*          repid     = sy-repid
*          dynnr     = sy-dynnr
*          extension = 300.
    ENDIF.

    CREATE OBJECT GR_TABLE
      EXPORTING
        I_PARENT = GR_CONTAINER.

    "展示ALV
    CALL METHOD GR_TABLE->SET_TABLE_FOR_FIRST_DISPLAY
      EXPORTING
        I_SAVE               = 'A'
        I_DEFAULT            = 'X'
        IS_LAYOUT            = GS_LAYOUT
        IT_TOOLBAR_EXCLUDING = LT_EXCL_FUNC
        I_STRUCTURE_NAME     = P_TABLE
      CHANGING
        IT_OUTTAB            = <DYN_TABLE>
        IT_FIELDCATALOG      = GT_FIELDCAT.

    "实例化“事件类”实例
    CREATE OBJECT GR_EVENT_RECEIVER.
    SET HANDLER GR_EVENT_RECEIVER->HANDLE_TOOLBAR FOR GR_TABLE.                 " 工具栏
    CALL METHOD GR_TABLE->SET_TOOLBAR_INTERACTIVE. " 调用工具条处理方法，使定义工具生效
    SET HANDLER GR_EVENT_RECEIVER->HANDLE_USER_COMMAND  FOR GR_TABLE.           " 用户响应事件
    SET HANDLER GR_EVENT_RECEIVER->HANDLE_DOUBLE_CLICK  FOR GR_TABLE.           " 双击事件
    SET HANDLER GR_EVENT_RECEIVER->HANDLE_HOTSPOT_CLICK FOR GR_TABLE.           " 热点事件
    SET HANDLER GR_EVENT_RECEIVER->HANDLE_DATA_CHANGED  FOR GR_TABLE.           " 数据修改事件
    CALL METHOD GR_TABLE->REGISTER_EDIT_EVENT
      EXPORTING
        I_EVENT_ID = CL_GUI_ALV_GRID=>MC_EVT_MODIFIED.                          " MC_EVT_ENTER:修改后，还要按ENTER才会触发
    SET HANDLER GR_EVENT_RECEIVER->HANDLE_DATA_CHANGED_FINISHED FOR GR_TABLE.   " 数据修改完成事件(触发改事件时，ALV内表已经被修改完毕了)

  ELSE.
    PERFORM FRM_REFRESH_DATA.
  ENDIF.
ENDFORM.                    " FRM_ALV_DISPLAY
*&---------------------------------------------------------------------*
*&      Form  FRM_LOAD_EXCEL
*&---------------------------------------------------------------------*
*       从EXCEL加载数据
*----------------------------------------------------------------------*
FORM FRM_LOAD_EXCEL USING UV_ROW UV_COL.
  DATA:LS_STRUCTURE TYPE REF TO DATA.
  DATA:LT_EXCEL LIKE ZALSMEX_TABLINE OCCURS 0 WITH HEADER LINE.
  FIELD-SYMBOLS:<L_FS_INTERN> TYPE ZALSMEX_TABLINE."表头行
*  FIELD-SYMBOLS:<l_fs_item> TYPE ty_alv.
  FIELD-SYMBOLS:<FIELD>.
  DATA:LV_ROW TYPE I,
       LV_COL TYPE I.

  DATA:LV_STR TYPE C LENGTH 1.

  LV_ROW = UV_ROW.
  LV_COL = UV_COL.


  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
    EXPORTING
      PERCENTAGE = 50
      TEXT       = '正在加载，请稍等'.


  CALL FUNCTION 'ZALSM_EXCEL_TO_INTERNAL_TABLE'
    EXPORTING
      FILENAME                = P_FILE
      I_BEGIN_COL             = LV_COL
      I_BEGIN_ROW             = LV_ROW
      I_END_COL               = 10
      I_END_ROW               = 60000
    TABLES
      INTERN                  = LT_EXCEL
    EXCEPTIONS
      INCONSISTENT_PARAMETERS = 1
      UPLOAD_OLE              = 2
      OTHERS                  = 3.
  IF SY-SUBRC <> 0.
    MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
    WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.

* 转换EXCEL数据到内表
*  CREATE DATA ls_structure LIKE dyn_wa.
  LOOP AT LT_EXCEL ASSIGNING <L_FS_INTERN>.
    AT NEW ROW.
      ASSIGN DYN_WA->* TO <DYN_WA>.
      INSERT <DYN_WA> INTO TABLE <DYN_TABLE> ASSIGNING <DYN_WA>.
    ENDAT.
    ASSIGN COMPONENT <L_FS_INTERN>-COL OF STRUCTURE <DYN_WA>
    TO <FIELD>.
    CHECK SY-SUBRC EQ 0.
    <FIELD> = <L_FS_INTERN>-VALUE.
  ENDLOOP.
ENDFORM.                    " FRM_LOAD_EXCEL
*&---------------------------------------------------------------------*
*&      Form  FRM_SAVE_DB
*&---------------------------------------------------------------------*
*       保存数据到数据库表
*----------------------------------------------------------------------*
FORM FRM_SAVE_DB .

  FIELD-SYMBOLS:<DYN_DB> TYPE STANDARD  TABLE,
                <DYN_DS> TYPE ANY.
  DATA:LT_TAB            TYPE REF TO DATA.
  DATA:LS_DATA           TYPE REF TO DATA.
  DATA:LV_FLAG           TYPE C.

  CREATE DATA LT_TAB TYPE TABLE OF (P_TABLE).
  ASSIGN LT_TAB->* TO <DYN_DB>.

  CREATE DATA LS_DATA LIKE LINE OF  <DYN_DB>.
  ASSIGN LS_DATA->* TO <DYN_DS>.

  LOOP AT <DYN_TABLE> ASSIGNING <DYN_WA>.
    ASSIGN COMPONENT 'SEL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
    IF <DYN_FIELD>  = 'X'.
      MOVE-CORRESPONDING <DYN_WA> TO <DYN_DS>.
      APPEND <DYN_DS> TO <DYN_DB>.
    ENDIF.
  ENDLOOP.

  IF LINES( <DYN_DB> ) > 0.
    LV_FLAG = 'X'.
  ENDIF.

  IF LV_FLAG = 'X'.
* 保存数据到底表
    IF R_ADD_M = 'X'.
      CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
        EXPORTING
          PERCENTAGE = 0
          TEXT       = '正在保存，请稍等'.
    ENDIF.

    MODIFY (P_TABLE) FROM TABLE <DYN_DB>.
    IF SY-SUBRC = 0.
      MESSAGE '保存成功！' TYPE 'S' .
      COMMIT WORK.
    ELSE.
      MESSAGE '保存失败！' TYPE 'S' DISPLAY LIKE 'E' .
      ROLLBACK WORK.
    ENDIF.

  ELSE.
    MESSAGE '请勾选有效数据!' TYPE 'E'.
  ENDIF.

ENDFORM.                    " FRM_SAVE_DB
*&---------------------------------------------------------------------*
*&      Module  STATUS_9001  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE STATUS_9001 OUTPUT.
  SET PF-STATUS 'STANDARD'.
*  SET TITLEBAR 'xxx'.
ENDMODULE.                 " STATUS_9001  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_9001  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE USER_COMMAND_9001 INPUT.
  SAVE_OK = OK_CODE.
  CLEAR OK_CODE.
  IF SAVE_OK = 'BACK' OR SAVE_OK = 'CANCEL'.
    LEAVE TO SCREEN 0 .
  ENDIF.
  IF SAVE_OK = 'EXIT' .
    LEAVE PROGRAM.
  ENDIF.
ENDMODULE.                 " USER_COMMAND_9001  INPUT
*&---------------------------------------------------------------------*
*&      Module  DISPLAY_ALV  OUTPUT
*&---------------------------------------------------------------------*
*       ALV展示
*----------------------------------------------------------------------*
MODULE DISPLAY_ALV OUTPUT.
  PERFORM FRM_DISPLAY_DATA.
ENDMODULE.                 " DISPLAY_ALV  OUTPUT
*&---------------------------------------------------------------------*
*&      Form  FRM_REFRESH_DATA
*&---------------------------------------------------------------------*
*       刷新数据
*----------------------------------------------------------------------*
FORM FRM_REFRESH_DATA .
  DATA:LV_STABLE TYPE LVC_S_STBL.   "刷新稳定性
  LV_STABLE-ROW = '1'.
  LV_STABLE-COL = '1'.


  PERFORM FRM_GET_DATA.             "重新获取一下数据"
  CALL METHOD GR_TABLE->REFRESH_TABLE_DISPLAY
    EXPORTING
      IS_STABLE = LV_STABLE.
ENDFORM.                    " FRM_REFRESH_DATA
*&---------------------------------------------------------------------*
*&      Form  FRM_DEL_ITEM
*&---------------------------------------------------------------------*
*       删除数据
*----------------------------------------------------------------------*
FORM FRM_DEL_ITEM .
  DATA:LT_ROWS TYPE LVC_T_ROW,
       LS_ROWS TYPE LVC_S_ROW.

  DATA:LV_FLAG  TYPE C.
  CALL METHOD GR_TABLE->GET_SELECTED_ROWS
    IMPORTING
      ET_INDEX_ROWS = LT_ROWS.

  FIELD-SYMBOLS:<DYN_DS> TYPE ANY.

  DATA:LS_DATA           TYPE REF TO DATA.

  CREATE DATA LS_DATA TYPE (P_TABLE).
  ASSIGN LS_DATA->* TO <DYN_DS>.
*   删除数据库表数据
  LOOP AT <DYN_TABLE> ASSIGNING <DYN_WA> .
    ASSIGN COMPONENT 'SEL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
    IF <DYN_FIELD> IS  ASSIGNED AND <DYN_FIELD> = 'X'.
      LV_FLAG = 'X'.
      MOVE-CORRESPONDING <DYN_WA> TO <DYN_DS>.
      DELETE (P_TABLE) FROM <DYN_DS> .
      IF SY-SUBRC = 0.
        COMMIT WORK .
      ENDIF.
    ENDIF.
  ENDLOOP.
  IF LV_FLAG  = 'X'.
*    刷新ALV内表数据
    MESSAGE '删除成功!' TYPE 'S'.
    PERFORM FRM_REFRESH_DATA.
  ELSE.
    MESSAGE '请勾选有效数据!' TYPE 'E'.

  ENDIF.
*  ENDIF.

ENDFORM.                    " FRM_DEL_ITEM
*&---------------------------------------------------------------------*
*&      Form  FRM_ADD_ITEM
*&---------------------------------------------------------------------*
*       添加单行数据
*----------------------------------------------------------------------*
FORM FRM_ADD_ITEM .
  DATA:LS_EDIT_CELL TYPE LVC_S_STYL,
       LT_EDIT_CELL TYPE LVC_T_STYL.
  DATA:LV_INDEX  TYPE I.
  LT_EDIT_CELL = GT_EDIT_CELL.
  LS_EDIT_CELL-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
  MODIFY LT_EDIT_CELL FROM LS_EDIT_CELL TRANSPORTING STYLE WHERE FIELDNAME <> 'MANDT'.
*  APPEND INITIAL LINE TO <dyn_table>.
  LV_INDEX = LINES( <DYN_TABLE> ) + 1.
  INSERT INITIAL LINE INTO <DYN_TABLE> INDEX LV_INDEX.
  "新增默认可编辑除MANDT字段"
  READ TABLE <DYN_TABLE> ASSIGNING <DYN_WA> WITH KEY ('MANDT') = ''.
  ASSIGN COMPONENT 'EDITCELL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
  IF <DYN_FIELD> IS ASSIGNED.
    <DYN_FIELD> = LT_EDIT_CELL.
  ENDIF.
  "新增默认赋值MANDT"
  ASSIGN COMPONENT 'MANDT' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
  IF <DYN_FIELD> IS ASSIGNED.
    <DYN_FIELD> = SY-MANDT.
  ENDIF.
  "新增默认勾选"
  ASSIGN COMPONENT 'SEL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
  IF <DYN_FIELD> IS ASSIGNED.
    <DYN_FIELD> = 'X'.
  ENDIF.
ENDFORM.                    " FRM_ADD_ITEM
*&---------------------------------------------------------------------*
*&      Form  FRM_MOD_ITEM
*&---------------------------------------------------------------------*
*       修改数据
*----------------------------------------------------------------------*
FORM FRM_MOD_ITEM .
  DATA:LS_EDIT_CELL TYPE LVC_S_STYL,
       LT_EDIT_CELL TYPE LVC_T_STYL.

  DATA:LS_FIELDCAT  TYPE LVC_S_FCAT.
  DATA:LV_FLAG      TYPE  C.

  "给字段设置可编辑"
  LT_EDIT_CELL = GT_EDIT_CELL.
  LS_EDIT_CELL-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
  LOOP AT GT_FIELDCAT INTO LS_FIELDCAT WHERE KEY = ''.
    MODIFY LT_EDIT_CELL FROM LS_EDIT_CELL TRANSPORTING STYLE WHERE
    FIELDNAME = LS_FIELDCAT-FIELDNAME AND FIELDNAME <> 'MANDT'.
  ENDLOOP.

  "找到需要编辑的记录
  LOOP AT <DYN_TABLE> ASSIGNING <DYN_WA>.
    ASSIGN COMPONENT 'SEL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
    IF <DYN_FIELD> IS  ASSIGNED AND <DYN_FIELD> = 'X'.
      LV_FLAG = 'X'.

      ASSIGN COMPONENT 'EDITCELL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
      IF <DYN_FIELD> IS ASSIGNED.
        <DYN_FIELD> = LT_EDIT_CELL.
      ENDIF.
    ENDIF.
  ENDLOOP.

  IF LV_FLAG = ''.        ""说明无勾选记录
    MESSAGE '请勾选有效数据!' TYPE 'E'.
  ENDIF.
ENDFORM.                    " FRM_MOD_ITEM
*&---------------------------------------------------------------------*
*&      Form  FRM_SALL_DATA
*&---------------------------------------------------------------------*
*       全选数据
*----------------------------------------------------------------------*
FORM FRM_SALL_DATA .
  LOOP AT <DYN_TABLE> ASSIGNING <DYN_WA>.
    ASSIGN COMPONENT 'SEL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
    IF <DYN_FIELD> IS ASSIGNED.
      <DYN_FIELD> = 'X'.
    ENDIF.
  ENDLOOP.
ENDFORM.                    " FRM_SALL_DATA
*&---------------------------------------------------------------------*
*&      Form  FRM_DSALL_DATA
*&---------------------------------------------------------------------*
*       取消全选
*----------------------------------------------------------------------*
FORM FRM_DSALL_DATA .
  LOOP AT <DYN_TABLE> ASSIGNING <DYN_WA>.
    ASSIGN COMPONENT 'SEL' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
    IF <DYN_FIELD> IS ASSIGNED.
      <DYN_FIELD> = ''.
    ENDIF.
  ENDLOOP.
ENDFORM.                    " FRM_DSALL_DATA
*&---------------------------------------------------------------------*
*&      Form  DOWNLOAD_TEMPLATE
*&---------------------------------------------------------------------*
*       下载维护模板
*----------------------------------------------------------------------*
FORM DOWNLOAD_TEMPLATE  USING   UV_TABLE.
  DATA LS_STRUCT TYPE REF TO CL_ABAP_STRUCTDESCR.
  DATA LR_TABLE  TYPE REF TO CL_ABAP_TABLEDESCR.
  DATA LT_COMP   TYPE ABAP_COMPONENT_TAB.
  DATA LS_COMP LIKE LINE OF LT_COMP.
  DATA LR_TYPE   TYPE REF TO CL_ABAP_TYPEDESCR.
  DATA LV_STRING TYPE STRING.
  DATA LV_INDEX  TYPE N.
  DATA LV_COUNT  TYPE I.
  DATA:LV_FIELD  TYPE FIELDNAME.
  DATA:LV_FILE   TYPE RLGRAP-FILENAME.

  CLEAR:LV_INDEX.
  "获取表字段数量"
  SELECT COUNT(*) INTO LV_COUNT FROM DD03L WHERE TABNAME = UV_TABLE.
  IF SY-SUBRC = 0.
    "循环拼接生成内表结构
    DO LV_COUNT TIMES.
      CLEAR:LV_STRING.
      LV_INDEX = LV_INDEX + 1.
      LV_STRING = 'FIELDNAME'.
      CALL METHOD CL_ABAP_DATADESCR=>DESCRIBE_BY_NAME
        EXPORTING
          P_NAME         = LV_STRING
        RECEIVING
          P_DESCR_REF    = LR_TYPE
        EXCEPTIONS
          TYPE_NOT_FOUND = 1
          OTHERS         = 2.
      IF SY-SUBRC <> 0.
        MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
        WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
      ENDIF.
      CONCATENATE 'FIELDNAME' LV_INDEX INTO LS_COMP-NAME.
      LS_COMP-TYPE ?= LR_TYPE.
      APPEND LS_COMP TO LT_COMP.
    ENDDO.

*根据字段目录创建动态结构类型
    CALL METHOD CL_ABAP_STRUCTDESCR=>CREATE
      EXPORTING
        P_COMPONENTS = LT_COMP
      RECEIVING
        P_RESULT     = LS_STRUCT.
*根据动态结构创建动态内表类型
    CALL METHOD CL_ABAP_TABLEDESCR=>CREATE
      EXPORTING
        P_LINE_TYPE = LS_STRUCT
      RECEIVING
        P_RESULT    = LR_TABLE.

*参照动态结构类型和动态内表类型创建内表与工作区
    CREATE DATA DYN_WA TYPE HANDLE LS_STRUCT.
    CREATE DATA DYN_TABLE TYPE HANDLE LR_TABLE.
*指定内表与工作区到字段符号
    ASSIGN DYN_WA->* TO <DYN_WA>.
    ASSIGN DYN_TABLE->* TO <DYN_TABLE>.

    "获取表字段"
    CALL FUNCTION 'NAMETAB_GET'
      EXPORTING
        LANGU               = SY-LANGU
        ONLY                = 'X'
        TABNAME             = UV_TABLE
      TABLES
        NAMETAB             = GT_TABLE
      EXCEPTIONS
        INTERNAL_ERROR      = 1
        TABLE_HAS_NO_FIELDS = 2
        TABLE_NOT_ACTIV     = 3
        NO_TEXTS_FOUND      = 4
        OTHERS              = 5.

    IF SY-SUBRC = 0.
      SORT GT_TABLE BY POSITION .
      CLEAR:LV_INDEX.
      "为模板内表赋值字段
      LOOP AT  GT_TABLE INTO GS_TABLE.
        LV_INDEX = LV_INDEX + 1.
        CONCATENATE 'FIELDNAME' LV_INDEX INTO LV_FIELD.
        ASSIGN COMPONENT LV_FIELD OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
        IF <DYN_FIELD> IS ASSIGNED.
          <DYN_FIELD> = GS_TABLE-FIELDNAME.
        ENDIF.
      ENDLOOP.
      APPEND <DYN_WA> TO <DYN_TABLE>.
      CLEAR:<DYN_WA>.
      ASSIGN COMPONENT 'FIELDNAME1' OF STRUCTURE <DYN_WA> TO <DYN_FIELD>.
      IF <DYN_FIELD> IS ASSIGNED.
        <DYN_FIELD> = '此列不需要维护。'.
      ENDIF.
      APPEND <DYN_WA> TO <DYN_TABLE>.
      "判断是否成功？
      IF LINES( <DYN_TABLE> ) > 0.
        PERFORM SAVE_EXCEL_FILE CHANGING LV_FILE.
        IF LV_FILE <> ''.
          "将内表数据下载到本地，类型为Excel"
          CALL FUNCTION 'WS_DOWNLOAD'
            EXPORTING
              FILENAME                = LV_FILE
              FILETYPE                = 'DAT'
            TABLES
              DATA_TAB                = <DYN_TABLE>  "被下载的内表
            EXCEPTIONS
              FILE_OPEN_ERROR         = 1
              FILE_WRITE_ERROR        = 2
              INVALID_FILESIZE        = 3
              INVALID_TYPE            = 4
              NO_BATCH                = 5
              UNKNOWN_ERROR           = 6
              INVALID_TABLE_WIDTH     = 7
              GUI_REFUSE_FILETRANSFER = 8
              CUSTOMER_ERROR          = 9
              NO_AUTHORITY            = 10
              OTHERS                  = 11.
          IF SY-SUBRC <> 0.
            MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
            WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDIF.
  ELSE.
    MESSAGE '请输入表名!' TYPE 'E'.
  ENDIF.

ENDFORM.                    " DOWNLOAD_TEMPLATE
*&---------------------------------------------------------------------*
*&      Form  FRM_CHECK_FILE_EXIST
*&---------------------------------------------------------------------*
*       检查文件路径
*----------------------------------------------------------------------*
FORM FRM_CHECK_FILE_EXIST  USING   UV_FILE.
  DATA:LV_FILE   TYPE STRING,
       LV_RESULT TYPE ABAP_BOOL.
  LV_FILE = UV_FILE.
  CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_EXIST
    EXPORTING
      FILE                 = LV_FILE
    RECEIVING
      RESULT               = LV_RESULT
    EXCEPTIONS
      CNTL_ERROR           = 1
      ERROR_NO_GUI         = 2
      WRONG_PARAMETER      = 3
      NOT_SUPPORTED_BY_GUI = 4
      OTHERS               = 5.
  IF LV_RESULT = ''.
    MESSAGE '文件路径不存在！'  TYPE 'E'.
  ENDIF.

ENDFORM.                    " FRM_CHECK_FILE_EXIST
*&---------------------------------------------------------------------*
*&      Form  SAVE_EXCEL_FILE
*&---------------------------------------------------------------------*
*       保存EXCEL文件
*----------------------------------------------------------------------*
FORM SAVE_EXCEL_FILE  CHANGING CV_FILE.
  DATA:LV_FILENAME     TYPE  STRING,
       LV_PATH         TYPE  STRING,
       LV_FULLPATH     TYPE  STRING,
       LV_DEFAULT_NAME TYPE  STRING.

  LV_DEFAULT_NAME = P_TABLE.

  CALL METHOD CL_GUI_FRONTEND_SERVICES=>FILE_SAVE_DIALOG
    EXPORTING
      WINDOW_TITLE              = '下载模板'
      DEFAULT_EXTENSION         = 'XLS'
      DEFAULT_FILE_NAME         = LV_DEFAULT_NAME
*     with_encoding             =
      FILE_FILTER               = CL_GUI_FRONTEND_SERVICES=>FILETYPE_EXCEL
*     initial_directory         =
*     prompt_on_overwrite       = 'X'
    CHANGING
      FILENAME                  = LV_FILENAME
      PATH                      = LV_PATH
      FULLPATH                  = LV_FULLPATH
*     user_action               =
*     file_encoding             =
    EXCEPTIONS
      CNTL_ERROR                = 1
      ERROR_NO_GUI              = 2
      NOT_SUPPORTED_BY_GUI      = 3
      INVALID_DEFAULT_FILE_NAME = 4
      OTHERS                    = 5.
  IF SY-SUBRC <> 0.
    MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
    WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ELSE.
    CV_FILE = LV_FULLPATH .
  ENDIF.
ENDFORM.                    " SAVE_EXCEL_FILE
*&---------------------------------------------------------------------*
*&      Form  FRM_CALL_SE16N
*&---------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
FORM FRM_CALL_SE16N .
  CALL FUNCTION 'SE16N_INTERFACE'
    EXPORTING
      I_TAB     = P_TABLE
      I_EDIT    = 'X'
      I_SAPEDIT = 'X'
*     I_NO_TXT  = ' '
*     I_MAX_LINES            = 500
*     I_LINE_DET             = ' '
*     I_DISPLAY = 'X'
*     I_CLNT_SPEZ            = ' '
*     I_CLNT_DEP             = ' '
*     I_VARIANT = ' '
*     I_OLD_ALV = ' '
*     I_CHECKKEY             = ' '
*     I_TECH_NAMES           = ' '
*     I_CWIDTH_OPT_OFF       = ' '
*     I_SCROLL  = ' '
*     I_NO_CONVEXIT          = ' '
*     I_LAYOUT_GET           = ' '
* IMPORTING
*     E_LINE_NR =
*     E_DREF    =
* TABLES
*     IT_SELFIELDS           =
*     IT_OUTPUT_FIELDS       =
*     IT_OR_SELFIELDS        =
    EXCEPTIONS
      NO_VALUES = 1
      OTHERS    = 2.
  IF SY-SUBRC <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.

ENDFORM.                    " FRM_CALL_SE16N
*&---------------------------------------------------------------------*
*&      Form  FRM_FILTER_DATA
*&---------------------------------------------------------------------*
*       过滤数据
*----------------------------------------------------------------------*
FORM FRM_FILTER_DATA .
  DATA:RANGE_STR       TYPE   STRING.
  DATA:LS_RSDS_WHERE   TYPE  RSDS_WHERE.
  DATA:LS_RSDSWHERE    TYPE  RSDSWHERE.
  READ TABLE GT_WHERE_CLAUSES INTO LS_RSDS_WHERE INDEX 1.
  IF SY-SUBRC = 0.
    LOOP AT LS_RSDS_WHERE-WHERE_TAB INTO LS_RSDSWHERE.
      CONCATENATE RANGE_STR LS_RSDSWHERE  INTO RANGE_STR SEPARATED BY SPACE.
    ENDLOOP.
  ENDIF.
  GV_SQL_WHERE = RANGE_STR.   "获取动态屏幕筛选条件"

ENDFORM.                    " FRM_FILTER_DATA
